// REST API implementation
use crate::websocket::WebSocketManager;
use axum::{
    extract::{ws::WebSocketUpgrade, Path, Query, State},
    http::StatusCode,
    response::{Json, Response},
    routing::{delete, get, post, put},
    Router,
};
use codegraph_core::{
    EdgeType, FileWatcher, GraphQueryEngine, GraphSystem, IncrementalParseEngine, NodeType,
    PerformanceMonitor, RelationshipDetectionEngine,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
use tower::ServiceBuilder;
use tower_http::cors::CorsLayer;

/// REST API server state
#[derive(Clone)]
pub struct ApiState {
    pub graph_system: Arc<RwLock<GraphSystem>>,
    pub query_engine: Arc<RwLock<GraphQueryEngine>>,
    pub relationship_engine: Arc<RwLock<RelationshipDetectionEngine>>,
    pub file_watcher: Arc<RwLock<Option<FileWatcher>>>,
    pub parse_engine: Arc<IncrementalParseEngine>,
    pub performance_monitor: Arc<PerformanceMonitor>,
    pub websocket_manager: Arc<WebSocketManager>,
}

/// REST API server
pub struct RestApiServer {
    state: ApiState,
    router: Router,
}

impl RestApiServer {
    pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
        let graph_system = Arc::new(RwLock::new(GraphSystem::new().await?));
        let query_engine = Arc::new(RwLock::new(GraphQueryEngine::new()));
        let relationship_engine = Arc::new(RwLock::new(RelationshipDetectionEngine::new(
            codegraph_core::relationship_detection::RelationshipConfig::default(),
        )));
        let parse_engine = Arc::new(IncrementalParseEngine::new());
        let file_watcher = Arc::new(RwLock::new(None));

        let performance_monitor = Arc::new(PerformanceMonitor::new());
        let websocket_manager = Arc::new(WebSocketManager::new(performance_monitor.clone()));

        let state = ApiState {
            graph_system,
            query_engine,
            relationship_engine,
            file_watcher,
            parse_engine,
            performance_monitor,
            websocket_manager,
        };

        let router = Self::create_router(state.clone());

        Ok(Self { state, router })
    }

    fn create_router(state: ApiState) -> Router {
        Router::new()
            // Health check
            .route("/health", get(health_check))

            // Graph operations
            .route("/api/v1/graph/build", post(build_graph))
            .route("/api/v1/graph/query", post(query_graph))
            .route("/api/v1/graph/stats", get(graph_stats))

            // Node operations
            .route("/api/v1/nodes", get(list_nodes))
            .route("/api/v1/nodes/:id", get(get_node))
            .route("/api/v1/nodes/:id", put(update_node))
            .route("/api/v1/nodes/:id", delete(delete_node))

            // Edge operations
            .route("/api/v1/edges", get(list_edges))
            .route("/api/v1/edges/:id", get(get_edge))
            .route("/api/v1/edges/:id", put(update_edge))
            .route("/api/v1/edges/:id", delete(delete_edge))

            // Relationship operations
            .route("/api/v1/relationships/detect", post(detect_relationships))
            .route("/api/v1/relationships/stats", get(relationship_stats))

            // File watching operations
            .route("/api/v1/watch/start", post(start_watching))
            .route("/api/v1/watch/stop", post(stop_watching))
            .route("/api/v1/watch/status", get(watch_status))

            // Query operations
            .route("/api/v1/query/advanced", post(advanced_query))
            .route("/api/v1/query/paths", post(find_paths))

            // System operations
            .route("/api/v1/system/status", get(system_status))
            .route("/api/v1/system/metrics", get(system_metrics))

            // WebSocket operations
            .route("/api/v1/ws", get(websocket_handler))
            .route("/api/v1/ws/stats", get(websocket_stats))

            .layer(
                ServiceBuilder::new()
                    .layer(CorsLayer::permissive())
            )
            .with_state(state)
    }

    pub fn router(&self) -> Router {
        self.router.clone()
    }

    pub async fn serve(self, host: &str, port: u16) -> Result<(), Box<dyn std::error::Error>> {
        let addr = format!("{}:{}", host, port);
        let listener = tokio::net::TcpListener::bind(&addr).await?;

        tracing::info!("REST API server listening on {}", addr);

        axum::serve(listener, self.router)
            .await
            .map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
    }
}

// API Request/Response types
#[derive(Debug, Serialize, Deserialize)]
pub struct BuildGraphRequest {
    pub project_path: String,
    pub languages: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BuildGraphResponse {
    pub success: bool,
    pub node_count: usize,
    pub edge_count: usize,
    pub languages: Vec<String>,
    pub build_time_ms: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct QueryGraphRequest {
    pub node_types: Option<Vec<String>>,
    pub edge_types: Option<Vec<String>>,
    pub languages: Option<Vec<String>>,
    pub name_pattern: Option<String>,
    pub limit: Option<usize>,
    pub offset: Option<usize>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct QueryGraphResponse {
    pub nodes: Vec<String>, // Node IDs as strings
    pub edges: Vec<String>, // Edge IDs as strings
    pub total_count: usize,
    pub execution_time_ms: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NodeResponse {
    pub id: String,
    pub node_type: String,
    pub name: String,
    pub language: String,
    pub location: LocationResponse,
    pub metadata: std::collections::HashMap<String, serde_json::Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LocationResponse {
    pub file_path: String,
    pub start_line: u32,
    pub start_column: u32,
    pub end_line: u32,
    pub end_column: u32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct EdgeResponse {
    pub id: String,
    pub source: String,
    pub target: String,
    pub edge_type: String,
    pub metadata: std::collections::HashMap<String, serde_json::Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct StartWatchingRequest {
    pub path: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WatchStatusResponse {
    pub is_watching: bool,
    pub watched_path: Option<String>,
    pub tracked_files: usize,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SystemStatusResponse {
    pub status: String,
    pub version: String,
    pub uptime_seconds: u64,
    pub memory_usage_mb: f64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ErrorResponse {
    pub error: String,
    pub code: Option<String>,
    pub details: Option<serde_json::Value>,
}

// Query parameters
#[derive(Debug, Deserialize)]
pub struct ListNodesQuery {
    pub limit: Option<usize>,
    pub offset: Option<usize>,
    pub node_type: Option<String>,
    pub language: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct ListEdgesQuery {
    pub limit: Option<usize>,
    pub offset: Option<usize>,
    pub edge_type: Option<String>,
    pub source: Option<String>,
    pub target: Option<String>,
}

// Handler functions
async fn health_check() -> Json<serde_json::Value> {
    Json(serde_json::json!({
        "status": "healthy",
        "timestamp": chrono::Utc::now().to_rfc3339(),
        "version": env!("CARGO_PKG_VERSION")
    }))
}

async fn build_graph(
    State(state): State<ApiState>,
    Json(request): Json<BuildGraphRequest>,
) -> Result<Json<BuildGraphResponse>, (StatusCode, Json<ErrorResponse>)> {
    let start_time = std::time::Instant::now();

    let mut graph_system = state.graph_system.write().await;
    let project_path = std::path::Path::new(&request.project_path);

    match graph_system
        .build_project_graph(
            project_path,
            request.languages.as_deref().map(|v| v.join(",")).as_deref(),
        )
        .await
    {
        Ok(graph) => {
            let build_time = start_time.elapsed().as_millis() as u64;
            Ok(Json(BuildGraphResponse {
                success: true,
                node_count: graph.node_count(),
                edge_count: graph.edge_count(),
                languages: graph.languages(),
                build_time_ms: build_time,
            }))
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to build graph: {}", e),
                code: Some("BUILD_FAILED".to_string()),
                details: None,
            }),
        )),
    }
}

async fn query_graph(
    State(state): State<ApiState>,
    Json(request): Json<QueryGraphRequest>,
) -> Result<Json<QueryGraphResponse>, (StatusCode, Json<ErrorResponse>)> {
    let mut query_engine = state.query_engine.write().await;

    // Convert request to GraphQuery
    let node_types = request.node_types.as_ref().map(|types| {
        types
            .iter()
            .filter_map(|t| match t.as_str() {
                "Function" => Some(NodeType::Function),
                "Class" => Some(NodeType::Class),
                "Variable" => Some(NodeType::Variable),
                "Import" => Some(NodeType::Import),
                _ => None,
            })
            .collect()
    });

    let edge_types = request.edge_types.as_ref().map(|types| {
        types
            .iter()
            .filter_map(|t| match t.as_str() {
                "Calls" => Some(EdgeType::Calls),
                "Inherits" => Some(EdgeType::Inherits),
                "References" => Some(EdgeType::References),
                "Imports" => Some(EdgeType::Imports),
                _ => None,
            })
            .collect()
    });

    let query = codegraph_core::GraphQuery {
        node_types,
        edge_types,
        languages: request.languages,
        name_pattern: request.name_pattern,
        location_filter: None,
        metadata_filter: None,
        limit: request.limit,
        offset: request.offset,
    };

    // For now, execute with empty node/edge sets (would be populated from actual graph)
    match query_engine.execute_query(&query, &[], &[]).await {
        Ok(result) => Ok(Json(QueryGraphResponse {
            nodes: result.nodes.iter().map(|id| id.to_string()).collect(),
            edges: result.edges.iter().map(|id| id.to_string()).collect(),
            total_count: result.nodes.len() + result.edges.len(),
            execution_time_ms: result.execution_time_ms,
        })),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Query failed: {}", e),
                code: Some("QUERY_FAILED".to_string()),
                details: None,
            }),
        )),
    }
}

async fn graph_stats(State(_state): State<ApiState>) -> Json<serde_json::Value> {
    // TODO: Implement actual graph statistics
    Json(serde_json::json!({
        "node_count": 0,
        "edge_count": 0,
        "languages": [],
        "last_updated": chrono::Utc::now().to_rfc3339()
    }))
}

async fn list_nodes(
    State(state): State<ApiState>,
    Query(params): Query<ListNodesQuery>,
) -> Json<Vec<NodeResponse>> {
    let mut query_engine = state.query_engine.write().await;

    // Build query from parameters
    let node_types = params.node_type.as_ref().map(|t| {
        vec![match t.as_str() {
            "Function" => NodeType::Function,
            "Class" => NodeType::Class,
            "Variable" => NodeType::Variable,
            "Import" => NodeType::Import,
            _ => NodeType::Unknown,
        }]
    });

    let languages = params.language.as_ref().map(|lang| vec![lang.clone()]);

    let query = codegraph_core::GraphQuery {
        node_types,
        edge_types: None,
        languages,
        name_pattern: None,
        location_filter: None,
        metadata_filter: None,
        limit: Some(params.limit.unwrap_or(50)),
        offset: params.offset,
    };

    // Execute query (with empty node/edge sets for now)
    match query_engine.execute_query(&query, &[], &[]).await {
        Ok(result) => {
            let nodes = result
                .nodes
                .iter()
                .map(|id| {
                    NodeResponse {
                        id: id.to_string(),
                        node_type: "unknown".to_string(), // TODO: Get actual node data
                        name: "unknown".to_string(),
                        language: "unknown".to_string(),
                        location: LocationResponse {
                            file_path: "unknown".to_string(),
                            start_line: 0,
                            start_column: 0,
                            end_line: 0,
                            end_column: 0,
                        },
                        metadata: std::collections::HashMap::new(),
                    }
                })
                .collect();
            Json(nodes)
        },
        Err(_) => {
            // Return empty list on error
            Json(vec![])
        },
    }
}

async fn get_node(
    State(state): State<ApiState>,
    Path(id): Path<String>,
) -> Result<Json<NodeResponse>, (StatusCode, Json<ErrorResponse>)> {
    // Parse node ID
    let node_id = match id.parse::<codegraph_core::NodeId>() {
        Ok(id) => id,
        Err(_) => {
            return Err((
                StatusCode::BAD_REQUEST,
                Json(ErrorResponse {
                    error: "Invalid node ID format".to_string(),
                    code: Some("INVALID_NODE_ID".to_string()),
                    details: None,
                }),
            ));
        },
    };

    // Get graph and find node
    match state.graph_system.read().await.get_project_graph() {
        Ok(graph) => {
            if let Some(node_ref) = graph.get_node(node_id) {
                match node_ref.read() {
                    Ok(node) => {
                        let response = NodeResponse {
                            id: node.id.to_string(),
                            node_type: format!("{:?}", node.node_type),
                            name: node.name.clone(),
                            language: node.language.clone(),
                            location: LocationResponse {
                                file_path: node.location.file_path.clone(),
                                start_line: node.location.start_line,
                                start_column: node.location.start_column,
                                end_line: node.location.end_line,
                                end_column: node.location.end_column,
                            },
                            metadata: std::collections::HashMap::new(),
                        };
                        Ok(Json(response))
                    },
                    Err(_) => Err((
                        StatusCode::INTERNAL_SERVER_ERROR,
                        Json(ErrorResponse {
                            error: "Failed to read node data".to_string(),
                            code: Some("NODE_READ_ERROR".to_string()),
                            details: None,
                        }),
                    )),
                }
            } else {
                Err((
                    StatusCode::NOT_FOUND,
                    Json(ErrorResponse {
                        error: "Node not found".to_string(),
                        code: Some("NODE_NOT_FOUND".to_string()),
                        details: None,
                    }),
                ))
            }
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to access graph: {}", e),
                code: Some("GRAPH_ACCESS_ERROR".to_string()),
                details: None,
            }),
        )),
    }
}

async fn update_node(
    State(_state): State<ApiState>,
    Path(_id): Path<String>,
    Json(_node): Json<NodeResponse>,
) -> Result<Json<NodeResponse>, (StatusCode, Json<ErrorResponse>)> {
    // TODO: Implement actual node update
    Err((
        StatusCode::NOT_IMPLEMENTED,
        Json(ErrorResponse {
            error: "Node update not implemented".to_string(),
            code: Some("NOT_IMPLEMENTED".to_string()),
            details: None,
        }),
    ))
}

async fn delete_node(
    State(state): State<ApiState>,
    Path(id): Path<String>,
) -> Result<StatusCode, (StatusCode, Json<ErrorResponse>)> {
    // Parse node ID
    let node_id = match id.parse::<codegraph_core::NodeId>() {
        Ok(id) => id,
        Err(_) => {
            return Err((
                StatusCode::BAD_REQUEST,
                Json(ErrorResponse {
                    error: "Invalid node ID format".to_string(),
                    code: Some("INVALID_NODE_ID".to_string()),
                    details: None,
                }),
            ));
        },
    };

    // Get mutable access to graph and remove node
    match state.graph_system.write().await.get_project_graph_mut() {
        Ok(graph) => {
            if graph.remove_node(node_id) {
                Ok(StatusCode::NO_CONTENT)
            } else {
                Err((
                    StatusCode::NOT_FOUND,
                    Json(ErrorResponse {
                        error: "Node not found".to_string(),
                        code: Some("NODE_NOT_FOUND".to_string()),
                        details: None,
                    }),
                ))
            }
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to access graph: {}", e),
                code: Some("GRAPH_ACCESS_ERROR".to_string()),
                details: None,
            }),
        )),
    }
}

async fn list_edges(
    State(state): State<ApiState>,
    Query(params): Query<ListEdgesQuery>,
) -> Json<Vec<EdgeResponse>> {
    match state.graph_system.read().await.get_project_graph() {
        Ok(graph) => {
            let mut edges: Vec<EdgeResponse> = graph
                .edges()
                .into_iter()
                .filter_map(|edge| {
                    // Apply filters
                    if let Some(ref edge_type_filter) = params.edge_type {
                        let edge_type_str = format!("{:?}", edge.edge_type);
                        if !edge_type_str.eq_ignore_ascii_case(edge_type_filter) {
                            return None;
                        }
                    }

                    if let Some(ref source_filter) = params.source {
                        if edge.source.to_string() != *source_filter {
                            return None;
                        }
                    }

                    if let Some(ref target_filter) = params.target {
                        if edge.target.to_string() != *target_filter {
                            return None;
                        }
                    }

                    Some(EdgeResponse {
                        id: edge.id.to_string(),
                        source: edge.source.to_string(),
                        target: edge.target.to_string(),
                        edge_type: format!("{:?}", edge.edge_type),
                        metadata: std::collections::HashMap::new(),
                    })
                })
                .collect();

            // Apply pagination
            let offset = params.offset.unwrap_or(0);
            let limit = params.limit.unwrap_or(100);

            if offset < edges.len() {
                edges = edges.into_iter().skip(offset).take(limit).collect();
            } else {
                edges.clear();
            }

            Json(edges)
        },
        Err(_) => Json(vec![]),
    }
}

async fn get_edge(
    State(state): State<ApiState>,
    Path(id): Path<String>,
) -> Result<Json<EdgeResponse>, (StatusCode, Json<ErrorResponse>)> {
    // Parse edge ID
    let edge_id = match id.parse::<codegraph_core::EdgeId>() {
        Ok(id) => id,
        Err(_) => {
            return Err((
                StatusCode::BAD_REQUEST,
                Json(ErrorResponse {
                    error: "Invalid edge ID format".to_string(),
                    code: Some("INVALID_EDGE_ID".to_string()),
                    details: None,
                }),
            ));
        },
    };

    // Get graph and find edge
    match state.graph_system.read().await.get_project_graph() {
        Ok(graph) => {
            if let Some(edge_ref) = graph.get_edge(edge_id) {
                match edge_ref.read() {
                    Ok(edge) => {
                        let response = EdgeResponse {
                            id: edge.id.to_string(),
                            source: edge.source.to_string(),
                            target: edge.target.to_string(),
                            edge_type: format!("{:?}", edge.edge_type),
                            metadata: std::collections::HashMap::new(),
                        };
                        Ok(Json(response))
                    },
                    Err(_) => Err((
                        StatusCode::INTERNAL_SERVER_ERROR,
                        Json(ErrorResponse {
                            error: "Failed to read edge data".to_string(),
                            code: Some("EDGE_READ_ERROR".to_string()),
                            details: None,
                        }),
                    )),
                }
            } else {
                Err((
                    StatusCode::NOT_FOUND,
                    Json(ErrorResponse {
                        error: "Edge not found".to_string(),
                        code: Some("EDGE_NOT_FOUND".to_string()),
                        details: None,
                    }),
                ))
            }
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to access graph: {}", e),
                code: Some("GRAPH_ACCESS_ERROR".to_string()),
                details: None,
            }),
        )),
    }
}

async fn update_edge(
    State(_state): State<ApiState>,
    Path(_id): Path<String>,
    Json(_edge): Json<EdgeResponse>,
) -> Result<Json<EdgeResponse>, (StatusCode, Json<ErrorResponse>)> {
    // TODO: Implement actual edge update
    Err((
        StatusCode::NOT_IMPLEMENTED,
        Json(ErrorResponse {
            error: "Edge update not implemented".to_string(),
            code: Some("NOT_IMPLEMENTED".to_string()),
            details: None,
        }),
    ))
}

async fn delete_edge(
    State(state): State<ApiState>,
    Path(id): Path<String>,
) -> Result<StatusCode, (StatusCode, Json<ErrorResponse>)> {
    // Parse edge ID
    let edge_id = match id.parse::<codegraph_core::EdgeId>() {
        Ok(id) => id,
        Err(_) => {
            return Err((
                StatusCode::BAD_REQUEST,
                Json(ErrorResponse {
                    error: "Invalid edge ID format".to_string(),
                    code: Some("INVALID_EDGE_ID".to_string()),
                    details: None,
                }),
            ));
        },
    };

    // Get mutable access to graph and remove edge
    match state.graph_system.write().await.get_project_graph_mut() {
        Ok(graph) => {
            if graph.remove_edge(edge_id) {
                Ok(StatusCode::NO_CONTENT)
            } else {
                Err((
                    StatusCode::NOT_FOUND,
                    Json(ErrorResponse {
                        error: "Edge not found".to_string(),
                        code: Some("EDGE_NOT_FOUND".to_string()),
                        details: None,
                    }),
                ))
            }
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to access graph: {}", e),
                code: Some("GRAPH_ACCESS_ERROR".to_string()),
                details: None,
            }),
        )),
    }
}

async fn detect_relationships(
    State(state): State<ApiState>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let start_time = std::time::Instant::now();
    let relationship_engine = state.relationship_engine.read().await;

    // For now, return a mock response since we don't have actual nodes/edges
    // In a real implementation, we would:
    // 1. Get all nodes and edges from the graph storage
    // 2. Run relationship detection algorithms
    // 3. Return the detected relationships

    match relationship_engine.detect_relationships(&[]).await {
        Ok(relationships) => {
            let detection_time = start_time.elapsed().as_millis() as u64;
            Ok(Json(serde_json::json!({
                "relationships": relationships.iter().map(|rel| {
                    serde_json::json!({
                        "source": rel.source.to_string(),
                        "target": rel.target.to_string(),
                        "edge_type": format!("{:?}", rel.edge_type),
                        "confidence": rel.confidence,
                        "evidence": rel.evidence
                    })
                }).collect::<Vec<_>>(),
                "total_count": relationships.len(),
                "detection_time_ms": detection_time
            })))
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Relationship detection failed: {}", e),
                code: Some("DETECTION_FAILED".to_string()),
                details: None,
            }),
        )),
    }
}

async fn relationship_stats(State(state): State<ApiState>) -> Json<serde_json::Value> {
    match state.graph_system.read().await.get_project_graph() {
        Ok(graph) => {
            let edges = graph.edges();
            let mut stats = std::collections::HashMap::new();
            let mut total_relationships = 0;

            // Count relationships by type
            for edge in edges {
                let edge_type = format!("{:?}", edge.edge_type);
                *stats.entry(edge_type).or_insert(0) += 1;
                total_relationships += 1;
            }

            Json(serde_json::json!({
                "total_relationships": total_relationships,
                "call_relationships": stats.get("Calls").unwrap_or(&0),
                "inheritance_relationships": stats.get("Inherits").unwrap_or(&0),
                "import_relationships": stats.get("Imports").unwrap_or(&0),
                "reference_relationships": stats.get("References").unwrap_or(&0),
                "contains_relationships": stats.get("Contains").unwrap_or(&0),
                "uses_relationships": stats.get("Uses").unwrap_or(&0),
                "depends_on_relationships": stats.get("DependsOn").unwrap_or(&0),
                "relationship_types": stats,
                "timestamp": chrono::Utc::now().to_rfc3339()
            }))
        },
        Err(_) => Json(serde_json::json!({
            "total_relationships": 0,
            "call_relationships": 0,
            "inheritance_relationships": 0,
            "import_relationships": 0,
            "error": "Failed to access graph"
        })),
    }
}

async fn start_watching(
    State(state): State<ApiState>,
    Json(request): Json<StartWatchingRequest>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let mut file_watcher_guard = state.file_watcher.write().await;

    // Stop existing watcher if any
    if let Some(mut existing_watcher) = file_watcher_guard.take() {
        let _ = existing_watcher.stop_watching().await;
    }

    // Create new file watcher
    let mut watcher = codegraph_core::FileWatcher::new(state.parse_engine.clone());
    let watch_path = std::path::Path::new(&request.path);

    match watcher.start_watching(watch_path).await {
        Ok(_) => {
            *file_watcher_guard = Some(watcher);
            Ok(Json(serde_json::json!({
                "success": true,
                "message": format!("File watching started for path: {}", request.path),
                "watched_path": request.path
            })))
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Failed to start watching: {}", e),
                code: Some("WATCH_START_FAILED".to_string()),
                details: None,
            }),
        )),
    }
}

async fn stop_watching(
    State(state): State<ApiState>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let mut file_watcher_guard = state.file_watcher.write().await;

    if let Some(mut watcher) = file_watcher_guard.take() {
        match watcher.stop_watching().await {
            Ok(_) => Ok(Json(serde_json::json!({
                "success": true,
                "message": "File watching stopped successfully"
            }))),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ErrorResponse {
                    error: format!("Failed to stop watching: {}", e),
                    code: Some("WATCH_STOP_FAILED".to_string()),
                    details: None,
                }),
            )),
        }
    } else {
        Ok(Json(serde_json::json!({
            "success": true,
            "message": "No active file watcher to stop"
        })))
    }
}

async fn watch_status(State(state): State<ApiState>) -> Json<WatchStatusResponse> {
    let file_watcher_guard = state.file_watcher.read().await;

    if let Some(watcher) = file_watcher_guard.as_ref() {
        let status = watcher.get_stats().await;
        Json(WatchStatusResponse {
            is_watching: status.is_watching,
            watched_path: None, // TODO: Add watched_path to WatcherStats if needed
            tracked_files: status.tracked_files_count,
        })
    } else {
        Json(WatchStatusResponse {
            is_watching: false,
            watched_path: None,
            tracked_files: 0,
        })
    }
}

async fn advanced_query(
    State(state): State<ApiState>,
    Json(builder_json): Json<serde_json::Value>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    let start_time = std::time::Instant::now();

    // Parse query builder from JSON
    let builder: codegraph_core::QueryBuilder = match serde_json::from_value(builder_json) {
        Ok(b) => b,
        Err(e) => {
            return Err((
                StatusCode::BAD_REQUEST,
                Json(ErrorResponse {
                    error: format!("Invalid query builder format: {}", e),
                    code: Some("INVALID_QUERY_FORMAT".to_string()),
                    details: None,
                }),
            ));
        },
    };

    let mut query_engine = state.query_engine.write().await;

    // Execute advanced query (with empty node/edge sets for now)
    match query_engine
        .execute_advanced_query(&builder, &[], &[])
        .await
    {
        Ok(result) => {
            let execution_time = start_time.elapsed().as_millis() as u64;

            Ok(Json(serde_json::json!({
                "nodes": result.nodes.iter().map(|id| id.to_string()).collect::<Vec<_>>(),
                "edges": result.edges.iter().map(|id| id.to_string()).collect::<Vec<_>>(),
                "paths": result.paths.iter().map(|path| {
                    serde_json::json!({
                        "nodes": path.nodes.iter().map(|id| id.to_string()).collect::<Vec<_>>(),
                        "edges": path.edges.iter().map(|id| id.to_string()).collect::<Vec<_>>(),
                        "length": path.length,
                        "weight": path.weight
                    })
                }).collect::<Vec<_>>(),
                "aggregations": result.aggregations,
                "metadata": result.metadata,
                "execution_time_ms": execution_time,
                "total_count": result.total_count,
                "has_more": result.has_more
            })))
        },
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ErrorResponse {
                error: format!("Advanced query failed: {}", e),
                code: Some("QUERY_FAILED".to_string()),
                details: None,
            }),
        )),
    }
}

async fn find_paths(
    State(_state): State<ApiState>,
    Json(_request): Json<serde_json::Value>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
    // TODO: Implement path finding
    Ok(Json(serde_json::json!({
        "paths": [],
        "total_count": 0,
        "execution_time_ms": 0
    })))
}

async fn system_status(State(state): State<ApiState>) -> Json<SystemStatusResponse> {
    let performance_monitor = &state.performance_monitor;
    let system_metrics = performance_monitor.get_metrics().await;

    // Calculate uptime (simplified - would need actual start time tracking)
    let uptime_seconds = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs()
        % 86400; // Mock uptime as seconds since midnight

    // Get the latest memory metric
    let latest_memory_metric = system_metrics.memory_metrics.latest();
    let memory_usage_mb = latest_memory_metric
        .map(|m| m.heap_used_bytes as f64 / (1024.0 * 1024.0))
        .unwrap_or(0.0);

    Json(SystemStatusResponse {
        status: "running".to_string(),
        version: env!("CARGO_PKG_VERSION").to_string(),
        uptime_seconds,
        memory_usage_mb,
    })
}

async fn system_metrics(State(state): State<ApiState>) -> Json<serde_json::Value> {
    let performance_monitor = &state.performance_monitor;
    let system_metrics = performance_monitor.get_metrics().await;
    let performance_report = performance_monitor.get_report().await;
    let websocket_stats = state.websocket_manager.get_connection_stats().await;

    // Get latest metrics
    let latest_system_metric = system_metrics.system_metrics.latest();
    let latest_memory_metric = system_metrics.memory_metrics.latest();

    Json(serde_json::json!({
        "cpu_usage_percent": latest_system_metric.map(|m| m.cpu_usage_percent).unwrap_or(0.0),
        "memory_usage_mb": latest_memory_metric.map(|m| m.heap_used_bytes as f64 / (1024.0 * 1024.0)).unwrap_or(0.0),
        "disk_usage_mb": latest_system_metric.map(|m| m.disk_usage_percent * 1024.0).unwrap_or(0.0), // Approximate
        "active_connections": websocket_stats.total_connections,
        "requests_per_second": performance_report.operation_stats.operations_per_second,
        "average_response_time_ms": performance_report.operation_stats.average_duration_ms,
        "total_requests": performance_report.operation_stats.total_operations,
        "error_rate": if performance_report.operation_stats.total_operations > 0 {
            performance_report.operation_stats.failed_operations as f64 / performance_report.operation_stats.total_operations as f64 * 100.0
        } else { 0.0 },
        "peak_memory_mb": performance_report.memory_stats.peak_heap_used_bytes as f64 / (1024.0 * 1024.0),
        "timestamp": chrono::Utc::now().to_rfc3339()
    }))
}

async fn websocket_handler(ws: WebSocketUpgrade, State(state): State<ApiState>) -> Response {
    state.websocket_manager.handle_websocket_upgrade(ws).await
}

async fn websocket_stats(State(state): State<ApiState>) -> Json<serde_json::Value> {
    let stats = state.websocket_manager.get_connection_stats().await;
    Json(serde_json::json!({
        "total_connections": stats.total_connections,
        "authenticated_connections": stats.authenticated_connections,
        "active_subscriptions": stats.active_subscriptions,
        "timestamp": chrono::Utc::now().to_rfc3339()
    }))
}
